using Dapper;
using MediatR;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using RBAC.Domain.Dto.Output;
using RBAC.Domain.ProcessManagement;
using RBAC.ErrorCode;
using RBAC.Interstructrue.Base;
using RBAC.Read.Api.Application.Command.ProcessManagements;

namespace RBAC.Read.Api.Application.Handler.ProcessManagements
{
    /// <summary>
    /// 工艺流程导出处理器（读端）
    /// </summary>
    public class ExportProcessFlowsHandler : IRequestHandler<ExportProcessFlowsCommand, APIResult<byte[]>>
    {
        private readonly IBaseRepository<ProcessFlow> _repo;

        public ExportProcessFlowsHandler(IBaseRepository<ProcessFlow> repo)
        {
            _repo = repo;
        }

        public async Task<APIResult<byte[]>> Handle(ExportProcessFlowsCommand request, CancellationToken cancellationToken)
        {
            try
            {
                var (where, param) = BuildWhere(request);

                var dataSql = $@"SELECT
                                        pf.Id,
                                        pf.FlowCode,
                                        pf.SystemCode,
                                        pf.FlowName,
                                        pf.ProcessCount,
                                        pf.OwnerUserId,
                                        COALESCE(u.UserName, pf.OwnerUserName) AS OwnerUserName,
                                        pf.DepartmentId,
                                        COALESCE(dm.DepartmentName, pf.DepartmentName) AS DepartmentName,
                                        pf.Status,
                                        pf.Remark,
                                        pf.CreateTime,
                                        pf.CreateUser
                                      FROM ProcessFlow pf
                                      LEFT JOIN Department dm ON pf.DepartmentId = dm.Id AND dm.IsDeleted = 0
                                      LEFT JOIN `User` u ON pf.OwnerUserId = u.Id AND u.IsDeleted = 0
                                      {(string.IsNullOrWhiteSpace(where) ? "" : "WHERE " + where)}
                                      ORDER BY {request.OrderBy}";

                var rows = _repo.Query<ProcessFlowListDto>(dataSql, param)?.ToList() ?? new List<ProcessFlowListDto>();
                if (rows.Count == 0)
                {
                    return new APIResult<byte[]>
                    {
                        Code = APIEnums.Fail,
                        Msg = "没有可导出的工艺流程数据",
                        Data = Array.Empty<byte>()
                    };
                }

                var wb = new XSSFWorkbook();
                var sheet = wb.CreateSheet("工艺流程");

                var headers = new[] { "工艺流程编码", "工艺流程名称", "工序数量", "负责人", "所属部门", "状态", "备注", "创建时间", "创建人" };
                var headerRow = sheet.CreateRow(0);
                for (int i = 0; i < headers.Length; i++) headerRow.CreateCell(i).SetCellValue(headers[i]);

                for (int r = 0; r < rows.Count; r++)
                {
                    var m = rows[r];
                    var row = sheet.CreateRow(r + 1);
                    row.CreateCell(0).SetCellValue(m.FlowCode ?? string.Empty);
                    row.CreateCell(1).SetCellValue(m.FlowName ?? string.Empty);
                    row.CreateCell(2).SetCellValue(Convert.ToInt64(m.ProcessCount ?? 0));
                    row.CreateCell(3).SetCellValue(m.OwnerUserName ?? string.Empty);
                    row.CreateCell(4).SetCellValue(m.DepartmentName ?? string.Empty);
                    row.CreateCell(5).SetCellValue(m.Status == 1 ? "启用" : "禁用");
                    row.CreateCell(6).SetCellValue(m.Remark ?? string.Empty);
                    row.CreateCell(7).SetCellValue(m.CreateTime.ToString("yyyy-MM-dd HH:mm:ss"));
                    row.CreateCell(8).SetCellValue(m.CreateUser ?? string.Empty);
                }

                using var ms = new MemoryStream();
                wb.Write(ms);
                ms.Flush();
                var bytes = ms.ToArray();

                return new APIResult<byte[]>
                {
                    Code = APIEnums.Success,
                    Msg = $"成功导出{rows.Count}条数据",
                    Data = bytes
                };
            }
            catch (Exception ex)
            {
                return new APIResult<byte[]>
                {
                    Code = APIEnums.Fail,
                    Msg = "导出失败：" + ex.Message,
                    Data = Array.Empty<byte>()
                };
            }
        }

        private static (string where, DynamicParameters param) BuildWhere(ExportProcessFlowsCommand req)
        {
            var conds = new List<string> { "pf.IsDeleted = 0" };
            var p = new DynamicParameters();

            if (!string.IsNullOrWhiteSpace(req.Keyword))
            {
                conds.Add("(pf.FlowCode LIKE @kw OR pf.FlowName LIKE @kw)");
                p.Add("@kw", $"%{req.Keyword}%");
            }
            if (req.DepartmentId.HasValue)
            {
                conds.Add("pf.DepartmentId = @DepartmentId");
                p.Add("@DepartmentId", req.DepartmentId.Value);
            }
            if (req.Status.HasValue)
            {
                conds.Add("pf.Status = @Status");
                p.Add("@Status", req.Status.Value);
            }

            var where = string.Join(" AND ", conds);
            return (where, p);
        }
    }
}
